home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / GridLayout.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  9.7 KB  |  295 lines  |  [TEXT/CWIE]

  1. // GridLayout.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp. All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. /** Object subclass implementing a LayoutManager that manages a grid of
  10.   * Views.  A GridLayout with zero rows and zero columns formatted as a square
  11.   * matrix large enough to hold all of the subviews. A zero in a single
  12.   * dimension indicates that dimension can grow without bounds. The
  13.   * GridLayout resizes all Views to have the same size.
  14.   * Note: Because Views do not call <b>layoutView()</b> whenever subviews are
  15.   * added or removed, an application using a GridLayout must explicitly call
  16.   * the GridLayout View's <b>layoutView()</b> with a zero delta width and delta
  17.   * height.  Calling <b>layoutView()</b> in this manner will cause the
  18.   * LayoutManager to properly position and size the View's subviews.
  19.   */
  20. public class GridLayout extends Object implements LayoutManager, Codable {
  21.     /** Number of rows in the Grid. */
  22.     int rowCount;
  23.     /** Number of columns in the Grid. */
  24.     int columnCount;
  25.     /** Horizontal gap between views in the Grid. */
  26.     int horizGap;
  27.     /** Vertical gap between views in the Grid. */
  28.     int vertGap;
  29.     /** How should the views be flowed into the Grid. */
  30.     int flowDirection;
  31.  
  32.     /** flowDirection value causing subviews to flow across the grid first. */
  33.     public static final int FLOW_ACROSS   = 0;
  34.     /** flowDirection value causing subviews to flow down the grid first. */
  35.     public static final int FLOW_DOWN     = 1;
  36.  
  37.  
  38.     final static String ROWCOUNT_KEY = "rowCount",
  39.                         COLUMNCOUNT_KEY = "columnCount",
  40.                         HORIZGAP_KEY = "horizGap",
  41.                         VERTGAP_KEY = "vertGap",
  42.                         FLOWDIRECTION_KEY = "flowDirection";
  43.  
  44.     /** Constructs a GridLayout with default values rowCount = 0,
  45.       * columnCount = 0, horizGap = 0, vertGap = 0, and flowDirection =
  46.       * FLOW_ACROSS/
  47.       */
  48.     public GridLayout()     {
  49.         this(0, 0, 0, 0, FLOW_ACROSS);
  50.     }
  51.  
  52.     /** Constructs a GridLayout with default values and <b>numRows</b> rows and
  53.       * <b>numCols</b> columns.
  54.       */
  55.     public GridLayout(int numRows, int numCols)     {
  56.         this(numRows, numCols, 0, 0, FLOW_ACROSS);
  57.     }
  58.  
  59.     /** Constructs a GridLayout with the specified values and <b>numRows</b>
  60.       * rows and <b>numCols</b> columns.
  61.       */
  62.     public GridLayout(int numRows, int numCols, int horizGap, int vertGap,
  63.                       int flow) {
  64.         setRowCount(numRows);
  65.         setColumnCount(numCols);
  66.         this.horizGap = horizGap;
  67.         this.vertGap  = vertGap;
  68.         setFlowDirection(flow);
  69.     }
  70.  
  71.     /** Sets the GridLayout to have <b>numRows</b> rows. */
  72.     public void setRowCount(int numRows)        {
  73.         rowCount = (numRows >= 0) ? numRows : 0;
  74.     }
  75.  
  76.     /** Returns the number of rows in the GridLayout.
  77.       * @see #setRowCount
  78.       */
  79.     public int rowCount() {
  80.         return rowCount;
  81.     }
  82.  
  83.     /** Sets the GridLayout to have <b>numCols</b> columns. */
  84.     public void setColumnCount(int numCols)        {
  85.         columnCount = (numCols >= 0) ? numCols : 0;
  86.     }
  87.  
  88.     /** Returns the number of columns in the GridLayout.
  89.       * @see #setColumnCount
  90.       */
  91.     public int columnCount() {
  92.         return columnCount;
  93.     }
  94.  
  95.     /** Sets the horizontal gap. */
  96.     public void setHorizGap(int gap) {
  97.         horizGap = gap;
  98.     }
  99.  
  100.     /** Returns the horizontal gap.
  101.       * @see #setHorizGap
  102.       */
  103.     public int horizGap() {
  104.         return horizGap;
  105.     }
  106.  
  107.     /** Sets the vertical gap. */
  108.     public void setVertGap(int gap) {
  109.         vertGap = gap;
  110.     }
  111.  
  112.     /** Returns the vertical gap.
  113.       * @see #setVertGap
  114.       */
  115.     public int vertGap() {
  116.         return vertGap;
  117.     }
  118.  
  119.     /** Sets the flow direction. */
  120.     public void setFlowDirection(int flow)      {
  121.         if(flow == FLOW_ACROSS || flow == FLOW_DOWN)
  122.             flowDirection = flow;
  123.         else
  124.             throw new InconsistencyException(this +
  125.                                 "Invalid Flow direction specified: " + flow);
  126.     }
  127.  
  128.     /** Returns the flow direction.
  129.       * @see #setFlowDirection
  130.       */
  131.     public int flowDirection() {
  132.         return flowDirection;
  133.     }
  134.  
  135.     /** LayoutManager interface method. GridLayout maintains no View-specific
  136.       * properties, so this method does nothing.
  137.       * @see LayoutManager
  138.       */
  139.     public void addSubview(View aView)      {
  140.     }
  141.  
  142.     /** LayoutManager interface method. GridLayout maintains no View-specific
  143.       * properties, so this method does nothing.
  144.       * @see LayoutManager
  145.       */
  146.     public void removeSubview(View aView){
  147.     }
  148.  
  149.     /** Resizes and positions all of the subviews to fit inside the specified
  150.       * grid.
  151.       * @see #gridSize
  152.       * @see LayoutManager
  153.       */
  154.     public void layoutView(View aView, int deltaWidth, int deltaHeight)    {
  155.         Vector theViews = aView.subviews();
  156.         int cnt,max;
  157.         int aveWidth, aveHeight;
  158.         int x,y;
  159.         View currView;
  160.         int curRow, curCol;
  161.         int nRows, nCols;
  162.         Size realGridSize;
  163.  
  164.         max = theViews.count();
  165.  
  166.         if(max < 1)
  167.             return;
  168.  
  169.         realGridSize = gridSize(aView);
  170.  
  171.         nCols = realGridSize.width;
  172.         nRows = realGridSize.height;
  173.  
  174.         aveWidth  = ((aView.bounds.width  - (horizGap*nCols)-horizGap) / nCols);
  175.         aveHeight = ((aView.bounds.height - (vertGap*nRows)-vertGap) / nRows);
  176.  
  177.         curRow = 0;
  178.         curCol = 0;
  179.  
  180.         if(flowDirection == FLOW_DOWN) {
  181.             /// FILL DOWN THE GRID
  182.             for(cnt=0;cnt<max;cnt++)        {
  183.                 x = ((aveWidth*curCol) + (horizGap*(curCol+1)));
  184.                 y = ((aveHeight*curRow) + (vertGap*(curRow+1)));
  185.                 currView = (View)theViews.elementAt(cnt);
  186.                 currView.setBounds(x, y, aveWidth, aveHeight);
  187.                 curRow++;
  188.                 if(nRows > 0 && curRow >= nRows)        {
  189.                     curCol++;
  190.                     curRow = 0;
  191.                 }
  192.             }
  193.         } else {
  194.             /// FILL ACROSS THE GRID
  195.             for(cnt=0;cnt<max;cnt++)        {
  196.                 x = ((aveWidth*curCol) + (horizGap*(curCol+1)));
  197.                 y = ((aveHeight*curRow) + (vertGap*(curRow+1)));
  198.                 currView = (View)theViews.elementAt(cnt);
  199.                 currView.setBounds(x, y, aveWidth, aveHeight);
  200.                 curCol++;
  201.                 if(nCols > 0 && curCol >= nCols)        {
  202.                     curRow++;
  203.                     curCol = 0;
  204.                 }
  205.             }
  206.         }
  207.     }
  208.  
  209.     /** Using the requested grid sizes and the number of subviews of
  210.       * <b>aView</b>, determines the actual size of the grid. Grids of
  211.       * size (0,0) are formatted as a square matrix large
  212.       * enough to hold all of the subviews. A zero in a single dimension
  213.       * indicates that dimension can grow without bounds. Grids with a non-zero
  214.       * <b>rowCount()</b> or <b>columnCount</b> and have more Views than
  215.       * (<b>rowCount()</b> * <b>columnCount</b>) will result in the extra Views
  216.       * being clipped. This method returns the actual size necessary to hold
  217.       * the current subviews of <b>parent</b>.  If <b>parent</b> contains no
  218.       * subviews, returns a Size with 0 extent.
  219.       */
  220.     public Size gridSize(View aView) {
  221.         int totalViews = aView.subviews().count();
  222.         int estRows, estCols;
  223.  
  224.         if(totalViews < 1)
  225.             return new Size();
  226.  
  227.         if(rowCount == 0)   {
  228.             if(columnCount == 0)   {
  229.                 // Determine closest square matrix
  230.                 estCols = (int)Math.ceil(Math.sqrt((float)totalViews));
  231.                 estRows = estCols;
  232.             } else {
  233.                 estCols = columnCount;
  234.                 estRows = (int)Math.ceil(((float)totalViews/estCols));
  235.             }
  236.         } else if(columnCount == 0)    {
  237.             if(rowCount == 0)   {
  238.                 // Determine closest square matrix
  239.                 estCols = (int)Math.ceil(Math.sqrt((float)totalViews));
  240.                 estRows = estCols;
  241.             } else {
  242.                 estRows = rowCount;
  243.                 estCols = (int)Math.ceil(((float)totalViews/estRows));
  244.             }
  245.         } else  {
  246.             estRows = rowCount;
  247.             estCols = columnCount;
  248.         }
  249.         return new Size(estCols, estRows);
  250.     }
  251.  
  252.  
  253. /// Codable Interface
  254.     /** Describes the GridLayout class' coding information.
  255.       * @see Codable#describeClassInfo
  256.       */
  257.     public void describeClassInfo(ClassInfo info)   {
  258.         info.addClass("netscape.application.GridLayout", 1);
  259.  
  260.         info.addField(ROWCOUNT_KEY, INT_TYPE);
  261.         info.addField(COLUMNCOUNT_KEY, INT_TYPE);
  262.         info.addField(HORIZGAP_KEY, INT_TYPE);
  263.         info.addField(VERTGAP_KEY, INT_TYPE);
  264.         info.addField(FLOWDIRECTION_KEY, INT_TYPE);
  265.     }
  266.  
  267.     /** Encodes the GridLayout.
  268.       * @see Codable#encode
  269.       */
  270.     public void decode(Decoder decoder) throws CodingException {
  271.         rowCount = decoder.decodeInt(ROWCOUNT_KEY);
  272.         columnCount = decoder.decodeInt(COLUMNCOUNT_KEY);
  273.         horizGap = decoder.decodeInt(HORIZGAP_KEY);
  274.         vertGap = decoder.decodeInt(VERTGAP_KEY);
  275.         flowDirection = decoder.decodeInt(FLOWDIRECTION_KEY);
  276.     }
  277.  
  278.     /** Decodes the GridLayout.
  279.       * @see Codable#decode
  280.       */
  281.     public void encode(Encoder encoder) throws CodingException {
  282.         encoder.encodeInt(ROWCOUNT_KEY, rowCount);
  283.         encoder.encodeInt(COLUMNCOUNT_KEY, columnCount);
  284.         encoder.encodeInt(HORIZGAP_KEY, horizGap);
  285.         encoder.encodeInt(VERTGAP_KEY, vertGap);
  286.         encoder.encodeInt(FLOWDIRECTION_KEY, flowDirection);
  287.     }
  288.  
  289.     /** Finishes the GridLayout's decoding.
  290.       * @see Codable#finishDecoding
  291.       */
  292.     public void finishDecoding() throws CodingException {
  293.     }
  294. }
  295.